/**
 * Generali Solutions d'assurances - Tous droits réservés &copy; 2007 - 2010
 */

package fr.generali.accueilclient.client.assembler.output;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import fr.generali.accueilclient.client.om.IClientAssociation;
import fr.generali.accueilclient.client.om.IClientAutre;
import fr.generali.accueilclient.client.om.IClientCollectivite;
import fr.generali.accueilclient.client.om.IClientCopropriete;
import fr.generali.accueilclient.client.om.IClientEntreprise;
import fr.generali.accueilclient.client.om.IClientParticulier;
import fr.generali.accueilclient.client.om.IClientProfessionnel;
import fr.generali.accueilclient.client.om.IPersonne;
import fr.generali.accueilclient.client.om.IPersonneMorale;
import fr.generali.accueilclient.client.om.IPersonnePhysique;
import fr.generali.accueilclient.client.om.NaturePersonne;
import fr.generali.refservcommuns.rce.consultpersonnesimple.dossierpersonnesimple.DtoDossierP41;
import fr.generali.refservcommuns.rce.servperscom.pty.personnes.DtoPersonneMorale;
import fr.generali.refservcommuns.rce.servperscom.pty.personnes.DtoPersonnePhysique;

/**
 * Transforme un {@link DtoDossierP41} en {@link IPersonne}
 * 
 * @author selrhazala
 */
@Component("dtoDossierP41ToPersonneConverter")
public class DtoDossierP41ToPersonneConverter implements Converter<DtoDossierP41, IPersonne> {

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(DtoDossierP41ToPersonneConverter.class);

    /**
     * Assembler de personne physique
     */
    @Autowired
    @Qualifier("dtoPersonnePhysique2PersonnePhysiqueConverter")
    private Converter<DtoPersonnePhysique, IPersonnePhysique> dtoPersonnePhysique2PersonnePhysiqueConverter;

    /**
     * Assembler de personne morale
     */
    @Autowired
    @Qualifier("dtoPersonneMorale2PersonneMoraleConverter")
    private Converter<DtoPersonneMorale, IPersonneMorale> dtoPersonneMorale2PersonneMoraleConverter;

    /**
     * Assembler pour un particulier
     */
    @Autowired
    @Qualifier("dtoDossierP41ToClientParticulierConverter")
    private Converter<DtoDossierP41, IClientParticulier> dtoDossierP41ToClientParticulierConverter;

    /**
     * Assembler pour un pro
     */
    @Autowired
    @Qualifier("dtoDossierP41ToClientProfessionnelConverter")
    private Converter<DtoDossierP41, IClientProfessionnel> dtoDossierP41ToClientProfessionnelConverter;

    /**
     * Assembler pour une association
     */
    @Autowired
    @Qualifier("dtoDossierP41ToClientAssociationConverter")
    private Converter<DtoDossierP41, IClientAssociation> dtoDossierP41ToClientAssociationConverter;

    /**
     * Assembler pour une collectivité
     */
    @Autowired
    @Qualifier("dtoDossierP41ToClientCollectiviteConverter")
    private Converter<DtoDossierP41, IClientCollectivite> dtoDossierP41ToClientCollectiviteConverter;

    /**
     * Assembler pour une copropriété
     */
    @Autowired
    @Qualifier("dtoDossierP41ToClientCoproprieteConverter")
    private Converter<DtoDossierP41, IClientCopropriete> dtoDossierP41ToClientCoproprieteConverter;

    /**
     * Assembler pour une entreprise
     */
    @Autowired
    @Qualifier("dtoDossierP41ToClientEntrepriseConverter")
    private Converter<DtoDossierP41, IClientEntreprise> dtoDossierP41ToClientEntrepriseConverter;

    /**
     * Assembler pour tout autre type de client
     */
    @Autowired
    @Qualifier("dtoDossierP41ToClientAutreConverter")
    private Converter<DtoDossierP41, IClientAutre> dtoDossierP41ToClientAutreConverter;

    /**
     * {@inheritDoc}
     */
    public IPersonne convert(DtoDossierP41 input) {
        LOGGER.debug("assemble");

        DtoPersonneMorale personneMorale = input.getPersonneMorale();
        DtoPersonnePhysique personnePhysique = input.getPersonnePhysique();
        boolean isPersonnePhysique = personneMorale == null && personnePhysique != null;
        boolean isPersonneMorale = personneMorale != null;
        NaturePersonne nature = calculerNature(personneMorale, personnePhysique, isPersonnePhysique, isPersonneMorale);

        IPersonne client = buildClient(input, nature);

        if (NaturePersonne.PARTICULIER.equals(nature) || NaturePersonne.PROFESSIONNEL.equals(nature)) {
            mapperPersonnePhysique(personnePhysique, client);
        } else {
            mapperPersonneMorale(personneMorale, client);
        }

        return client;
    }
    
    /**
     * Détermine la nature de la personne
     * 
     * @param personneMorale la personne morale
     * @param personnePhysique la personne physique
     * @param isPersonnePhysique true si c'est une personne physique
     * @param isPersonneMorale true si c'est une personne morale
     * @return la nature de la personne
     */
    private NaturePersonne calculerNature(DtoPersonneMorale personneMorale, DtoPersonnePhysique personnePhysique,
                    boolean isPersonnePhysique, boolean isPersonneMorale) {
        NaturePersonne nature = NaturePersonne.PARTICULIER;
        if (isPersonnePhysique && personnePhysique.getParticulierProfessionnel() != null
                        && !personnePhysique.getParticulierProfessionnel().isEmpty()) {
            nature = NaturePersonne.PROFESSIONNEL;
        } else {
            if (isPersonneMorale) {
                nature = NaturePersonne.getNaturePersonneFromValue(personneMorale.getTypePersonneMorale());
            }
        }
        return nature;
    }

    /**
     * @param input un {@link DtoDossierP41}
     * @param nature la nature personne
     * @return une personne
     */
    private IPersonne buildClient(DtoDossierP41 input, NaturePersonne nature) {
        IPersonne client;
        switch (nature) {
            case PARTICULIER:
                client = dtoDossierP41ToClientParticulierConverter.convert(input);
                break;
            case PROFESSIONNEL:
                client = dtoDossierP41ToClientProfessionnelConverter.convert(input);
                break;
            case ASSOCIATION:
                client = dtoDossierP41ToClientAssociationConverter.convert(input);
                break;
            case COLLECTIVITE:
                client = dtoDossierP41ToClientCollectiviteConverter.convert(input);
                break;
            case COPROPRIETE:
                client = dtoDossierP41ToClientCoproprieteConverter.convert(input);
                break;
            case ENTREPRISE:
                client = dtoDossierP41ToClientEntrepriseConverter.convert(input);
                break;
            default:
                client = dtoDossierP41ToClientAutreConverter.convert(input);
                break;
        }
        return client;
    }

    /**
     * Mappe une personne physique
     * 
     * @param personnePhysique la personne physique
     * @param client la personne
     */
    private void mapperPersonnePhysique(DtoPersonnePhysique personnePhysique, IPersonne client) {
        // Récupération des informations du niveau IPersonnePhysique
        IPersonnePhysique.class.cast(client).setPersonnePhysique(
                        dtoPersonnePhysique2PersonnePhysiqueConverter.convert(personnePhysique));
        // Récupération des informations du niveau IPersonne
        client.setNumeroClient(personnePhysique.getIdentifiantPersonne());
        if (StringUtils.isNotEmpty(personnePhysique.getVisibilite().getIdentifiantClientAgent())) {
            client.setNumeroClientAgent(personnePhysique.getVisibilite().getIdentifiantClientAgent());
        }
        client.setCodeIntermediaire(personnePhysique.getVisibilite().getIdentifiantIntermediaire());
        client.setTypeClient(personnePhysique.getStatutClient());
        if (personnePhysique.getDateDebutClient() != null) {
            client.setDateDebut(personnePhysique.getDateDebutClient().toGregorianCalendar().getTime());
            client.setDatePassageClient(personnePhysique.getDateDebutClient().toGregorianCalendar().getTime());
        }
        
        if (personnePhysique.getDateFinClient() != null) {
            client.setDateFinClient(personnePhysique.getDateFinClient().toGregorianCalendar().getTime());
        }
    }

    /**
     * Mappe une personne morale
     * 
     * @param personneMorale la personne morale
     * @param client la personne
     */
    private void mapperPersonneMorale(DtoPersonneMorale personneMorale, IPersonne client) {
        // Récupération des informations du niveau IPersonneMorale
        IPersonneMorale.class.cast(client).setPersonneMorale(
                        dtoPersonneMorale2PersonneMoraleConverter.convert(personneMorale));
        // Récupération des informations du niveau IPersonne
        client.setNumeroClient(personneMorale.getIdentifiantPersonne());
        if (StringUtils.isNotEmpty(personneMorale.getVisibilite().getIdentifiantClientAgent())) {
            client.setNumeroClientAgent(personneMorale.getVisibilite().getIdentifiantClientAgent());
        }
        client.setCodeIntermediaire(personneMorale.getVisibilite().getIdentifiantIntermediaire());
        client.setTypeClient(personneMorale.getStatutClient());
        if (personneMorale.getDateDebutClient() != null) {
            client.setDateDebut(personneMorale.getDateDebutClient().toGregorianCalendar().getTime());
            client.setDatePassageClient(personneMorale.getDateDebutClient().toGregorianCalendar().getTime());
        }
        
        if (personneMorale.getDateFinClient() != null) {
            client.setDateFinClient(personneMorale.getDateFinClient().toGregorianCalendar().getTime());
        }
    }

}
